package api;

import api.connection.DBConnection;
import api.result.Result;
import api.result.ResultList;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public abstract class Terminal implements Runnable{
    protected int terminalID;
    protected int numTerminal;
    protected BenchmarkModule benchmarkModule;
    protected Configuration config;
    protected double time;
    protected double rate;
    protected List<Double> weights;
    protected List<String> procedures;
    protected Worker worker;
    protected ResultList results;

    public Terminal(BenchmarkModule benchmarkModule, Configuration config, int terminalID) {
        this.benchmarkModule = benchmarkModule;
        this.config = config;
        this.time = config.getTime();
        this.rate = config.getRate();
        this.weights = config.getWeights();
        this.procedures = config.getProcedures();
        this.terminalID = terminalID;
        this.numTerminal = config.getTerminals();
        this.results = new ResultList();
        double sum = 0;
        for (Double weight : weights) {
            sum += weight;
        }
        for (int i = 0; i < weights.size(); i++) {
            weights.set(i, weights.get(i) / sum);
        }
    }

    public ResultList getResults() {
        return results;
    }

    public void run() {
        Random random = new Random(System.currentTimeMillis());
        long startTime = System.currentTimeMillis();
        int next = -1;
        for (int i = 0; i < rate; i++) {
            long delta = System.currentTimeMillis() - startTime;
            if (delta > time * 60 * 1000) {
                break;
            }
            next = pickNextProcedure(next, random);
            DBConnection connection = benchmarkModule.makeConnection();
            Result result = worker.executeProcedure(connection, procedures.get(next));
            results.union(result);
        }
    }

    /***
     * 用于选取下一个Procedure。
     * 对于TPC-C，按比例随机选取事务；对于TPC-H，按顺序选取（重载该方法）
     * @param current 当前Procedure的index
     * @param random 随机数生成器
     * @return 下一个Procedure的index
     */
    protected int pickNextProcedure(int current, Random random) {
        double tmp = random.nextDouble();
        for (int i = 0; i < weights.size(); i++) {
            tmp -= weights.get(i);
            if (tmp < 0) {
                return i;
            }
        }
        return weights.size() - 1;
    }
}
